package com.neusoft.hifly.gateway.filter;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.fastjson.JSON;

import com.neusoft.hifly.gateway.config.JwtConfig;
import com.neusoft.hifly.gateway.domain.ApiManagerVO;
import com.neusoft.hifly.gateway.utils.JwtUtil;
import com.neusoft.hifly.gateway.utils.RedisKeys;
import com.neusoft.hifly.gateway.utils.TokenMethod;
import com.neusoft.hifly.lock.utils.Log;
import com.neusoft.hifly.lock.utils.RedisContent;
import reactor.core.publisher.Mono;

/**
 * gateway全局过滤器，实现权限验证
 */
public class TokenFilter implements GlobalFilter, Ordered {

	@Autowired(required = false)
	private RedissonClient redisson;

	@Autowired(required = false)
	private JwtConfig jwtConfig;

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

		String path = exchange.getRequest().getURI().getPath();
		String mathod = exchange.getRequest().getMethod().toString();

		HttpHeaders headers = exchange.getRequest().getHeaders();
		List<String> tokens = headers.get(JwtUtil.TOKEN_KEY);
		// 这里只做有Token信息的认证，没有token说明是开放接口
		if (tokens != null && !tokens.isEmpty()) {
			final String token = tokens.get(0);
			if (StringUtils.isNotEmpty(token)) {
				// 解析角色信息
				final long organLogicId = (long) JwtUtil.getByKey(jwtConfig.getSecret(), token, JwtUtil.ORGAN_ID);
				final String roleIds = (String) JwtUtil.getByKey(jwtConfig.getSecret(), token, JwtUtil.ROLE_ID);
				Log.info("当前Token的角色信息：" + roleIds);
				// 这里做宽泛处理，也就是，没有明确指定的授权信息的，相当于可以访问所有

				if (organLogicId > 0 || StringUtils.isNotEmpty(roleIds)) {

					String[] roleArr = roleIds.split(",");
					for (String roleLogicId : roleArr) {
						if (StringUtils.isEmpty(roleLogicId)) {
							continue;
						}
						final RList<Object> list = redisson.getList(RedisKeys.API_POWER.getKey() + RedisContent.S
								+ organLogicId + RedisContent.S + roleLogicId);
						List<Object> readAll = list.readAll();
						if (readAll != null && !readAll.isEmpty()) {
							for (Object json : readAll) {
								final ApiManagerVO vo = JSON.parseObject(String.valueOf(json), ApiManagerVO.class);
								if (vo != null) {
									boolean isOk = checkPath(vo.getPath(), vo.getMethod(), path, mathod);
									if (!isOk) {
										// 返回401：请求要求身份验证。
										exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
										return exchange.getResponse().setComplete();
									}
								}
							}
						}
					}
				}
			}
		}
		return chain.filter(exchange);
	}

	@Override
	public int getOrder() {
		return -100;
	}

	private boolean checkPath(String paths, String method, String checkPath, String checkMethod) {
		boolean isOk = false;
		if ("**".equals(StringUtils.substring(paths, paths.length() - 2))) {
			// 1、处理**
			if (checkPath.indexOf(StringUtils.substringBeforeLast(paths, "**")) == 0) {
				isOk = true;
			}
		} else {
			// 2、处理全路径
			if (paths.equals(checkPath)) {
				isOk = true;
			}
		}

		if (isOk) {
			// 3、处理请求类型
			if (TokenMethod.ALL.getMethod().equalsIgnoreCase(method)) {
				isOk = true;
			} else {
				if (checkMethod.equalsIgnoreCase(method)) {
					isOk = true;
				}
			}
		}

		return isOk;
	}

}
